Here's my simple code which draws rectangle on frame.How can I add button to this frame? I tried to set FlowLayout but then rectangle is not visible.Help please.
import java.awt.*;
import javax.swing.*;
public class test extends Canvas{
public static JFrame frame;
public static JButton button;
public void paint(Graphics graphics) {
graphics.setColor(Color.yellow);
graphics.fillRect(10, 10, 100, 100);
graphics.setColor(Color.red);
graphics.drawRect(10, 10, 100, 100);
}
public static void main(String args[]){
test x=new test();
frame=new JFrame();
button=new JButton();
button.setSize(20,20);
button.setText("Click");
frame.setSize(500,500);
frame.add(button);
frame.add(x);
frame.setVisible(true);
}
}
The default layout for a JFrame is BorderLayout which can only accept one component per layout constraint. The default when none is specified is CENTER. So change:
frame.add(button);
frame.add(x);
To:
frame.add(button, BorderLayout.PAGE_START);
frame.add(x);
And you should see both components.
Other tips:
Don't set the size of top level containers. Instead layout the content & call pack().
Don't mix Swing & AWT without good reason. As the other poster mentioned, we'd typically use a JPanel for custom rendering in Swing.
The BorderLayout will ignore the size of the button and stretch it to fit. To have it stay a certain size, set a preferred size and add it to a FlowLayout. Add the FlowLayout to the PAGE_START constraint.
Don't paint onto a Canvas. Paint onto a JPanel.
Have your class extend JPanel, and then override paintComponent(Graphics g). Don't forget to call super.paintComponent()!
you must use Container, get Container of the frame then use layouts and add components to it using add() method.
Related
A quick and simple(?) question I can't seem to find an answer to.
Is it possible to draw a shape (rectangle, oval etc) and add to the JPanel, then add this JPanel to the JFrame? The examples of drawing with Graphics I found online added the shape directly to the JFrame. Example:
public class DShape extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GREEN);
g.drawRect(10,10,100,30);
}
public class Test {
public static void main(String[] args)
{
JFrame frame = new JFrame();
DShape shape = new DShape();
JPanel panel = new JPanel();
panel.add(shape);
frame.add(panel);
frame.setSize(200,200);
frame.setVisible(true);
}
}
This code will simply display a blank JFrame. A green rectangle will be displayed if you add a DShape class object directly to the JFrame. Is it possible to add the shape to JPanel first, then add JPanel to JFrame? Thank you.
The examples of drawing with Graphics I found online added the shape directly to the JFrame.
When you add the panel to the frame directly the default layout of the content pane is a BorderLayout, so the component gets resized to the size of the frame.
Is it possible to draw a shape (rectangle, oval etc) and add to the JPanel, then add this JPanel to the JFrame?
JFrame frame = new JFrame();
DShape shape = new DShape();
JPanel panel = new JPanel();
panel.add(shape);
frame.add(panel);
The default layout manager for a JPanel is the FlowLayout. A FlowLayout respects the preferred size of a component added to it. Your component doesn't have a preferred size so the size is (0, 0) so there is nothing to paint.
You need to override the getPreferredSize() method of your DShape panel to return the appropriate size.
Read the section from the Swing tutorial on Custom Painting for more information and working example.
Recently, I've met an issue that the paintComponent function is not invoked in the function, and I found that when I use splitpane function, it will disable the paint function, and gives error:
cannot add to layout: unknown constraint: null
I think the paint function may not be added to the right way, below is my code(partly):
Class: test
public class Test extends JFrame{
public Test() throws IOException{
//JFrame jf = new JFrame("my frame");
this.add(new NewPanel(this));
this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
this.setBounds(300,200,1050,600);
this.setVisible (true);
}
public static void main (String[] args) throws IOException{
Test test = new Test ();
test.setTitle("Hello");
//frame.pack ();
}
}
Class: NewPanel
public class NewPanel extends JPanel{
public NewPanel(JFrame frame) throws IOException{
JTabbedPane jTabbedpane = new JTabbedPane();
JSplitPane splitPane = new JSplitPane();
JPanel p1 = new JPanel();
p1.setLayout(null);
p2.setLayout(new FlowLayout());
splitPane.setOneTouchExpandable(true);
splitPane.setContinuousLayout(true);
//splitPane.setPreferredSize(new Dimension (250,500));
splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
splitPane.setLeftComponent(p1);
splitPane.setRightComponent (p2);
splitPane.setDividerSize(3);
splitPane.setDividerLocation(250); //balance two panels width
jTabbedpane.addTab("ABC",p2);
jTabbedpane.addTab("AB",p3);
jTabbedpane.addTab("AC",p4);
jTabbedpane.addTab("BC",p5);
frame.setContentPane(splitPane);
frame.add(jTabbedpane);
}
}
public void paintComponent(Graphics g){
super.paint(g);
g.setColor(Color.BLUE);
g.drawLine(303, 90, 303, 200);
g.drawLine(583, 90, 583, 200);
g.drawLine(863, 90, 863, 200);
}
}
When I comment frame.add(jTabbedpane),the line could be drawn in the panel, BUT it is only available in one panel, I cannot draw it into another split panel, I don't know why.. And when I uncomment frame.add(jTabbedpane), it pops up the above mentioned error.
Your UI assembly doesn't make sense. You're calling 'setContentPane' to the splitpane, which is sort-of OK (but unusual), but then you're calling add() to the frame, which tries to then add something else to the contentPane (the JSplitPane). You should either add the JTabbedPane to the SplitPane before adding the splitPane to the JPanel, or set up your layout differently.
//These don't make sense together.
frame.setContentPane(splitPane);
frame.add(jTabbedpane);
Your second question about drawing the blue line is more complicated.
You're doing a bunch of crazy stuff - you're creating a NewPanel and trying to add it to the JFrame, but then you're setting the contentPane of the JFrame to a different component later. You need to go through the Swing Tutorial and lay out your UI better.
I think the paint function may not be added to the right way,
public void paintComponent(Graphics g){
super.paint(g);
You are overriding paintComponent(...), so why are you calling super.paint(...)?
Start by reading the Swing Tutorial for Swing basics. All sections in the tutorial have working examples you can download and test.
So you might start with:
How to Use Split Panes - it will show you how to add a split pane to a frame
Performing Custom Painting - it will explain how painting works and show how to override the paintComponent(...) method.
I have a JFrame, which contains just a JPanel.
I add an mouse event to the JPanel.
But the whole JFrame gets the same mouse event.
Here is my code:
public class TestSwing extends JPanel {
public TestSwing() {
super.setSize(20, 20);
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
System.out.println(me);
}
});
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new TestSwing());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
}
}
I set the size of the JPanel (20, 20), but no matter where I click, the mouse event will always be triggered.
You're adding that JPanel to the JFrame's contentPane, a component that uses BorderLayout, a layout which does not respect size or even for the most part preferred size, and so the JPanel will fill the entire JFrame's contentPane. Give the contentPane a FlowLayout and set the JPanel's preferred size and you'll see a difference. In the future, give the JPanel a Border to see its boundaries. This will make debugging this easy.
If you don't tell it otherwise, your JFrame will have BorderLayout like this:
Now if you furthermore don't tell your Panel where to go, it wil go into CENTER and thus be resized to fill whole content area.
For checking MouseEvent on only one JPanel I suggest you add another JPanel (maybe with different background?) to other area:
frame.getContentPane().add(new TestSwing(), BorderLayout.CENTER);
JPanel left = new JPanel();
left.setBackground(Color.red);
frame.getContentPane().add(left, BorderLayout.LEFT);
Size set by setSize() is only valid until it's recalculated based on Layout and other properties.
I have a custom JPanel. The only thing that is in it, is a drawing of a rectangle, using the drawRect method of the Graphics object. The JPanel is always in a very specific square size, refuses to get any bigger or smaller. Tried overriding the getPreferredSize() method, didn't work.
Tried setting different layout managers for this custom JPanel, and also tried every layout manager for the JPanel that hosts this JPanel. Still, the size of the custom JPanel stays the same.
As I said, the custom JPanel has no components in it, only a drawing of a rectangle.
Any ideas?
Without knowing more about what you're trying to achieve:
As far as your containing panel, you need to know which layout managers respect preferred sizes and which ones don't
Grid Flow Border Box GridBag
Respect PreferredSize NO YES NO YES YES
That being said, if you wrap the painted JPanel in a JPanel with one of the "NOs", the painted JPanel shoud stretch with the resizing of the frame.
Also if you want the drawn rectangle to stretch along with its JPanel, then you need to remember to draw the rectangle with getWidth() and getHeight() of the JPanel and not use hard coded values.
Here is an example using BorderLayout as the containing panel's layout, and making use of getWidth() and getHeight() when performing the painting.
import java.awt.*;
import javax.swing.*;
public class StretchRect {
public StretchRect() {
JPanel panel = new JPanel(new BorderLayout());
panel.add(new RectanglePanel());
JFrame frame = new JFrame();
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public class RectanglePanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect( (int)(getWidth() * 0.1), (int)(getHeight() * 0.1),
(int)(getWidth() * 0.8), (int)(getHeight() * 0.8) );
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new StretchRect();
}
});
}
}
In following code I have set background color the content pane of the JFrame to black and JPanel to red. But when I am trying to setSize() with different sizes, red area does not contract or expend why is it so?
import java.awt.*;
import javax.swing.*;
public class exp{
public static void main(String args[]){
JFrame jf=new JFrame("This is JFrame");
JPanel h=new JPanel();
h.setSize(400,500);
h.add(new JButton("Button"));
h.add(new JLabel("this is JLabel"));
h.setBackground(Color.RED);
jf.add(h);
jf.getContentPane().setBackground(Color.BLACK);
jf.setLayout(new FlowLayout());
jf.setVisible(true);
jf.setSize(600,800);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
A JPanel is typically used as a container for components or other containers. The size of the panel is determined more by the size of the content and the layout and layout constraint with which it is added, than any size set on it.
What you seem to by trying here, can best be achieved by setting an EmptyBorder to the panel. E.G.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class exp{
public static void main(String args[]){
Runnable r = new Runnable() {
public void run() {
JFrame jf=new JFrame("This is JFrame");
JPanel h=new JPanel();
// add more space around the panel!
h.setBorder(new EmptyBorder(50,50,50,50));
h.add(new JButton("Button"));
h.add(new JLabel("this is JLabel"));
h.setBackground(Color.RED);
jf.add(h);
jf.getContentPane().setBackground(Color.BLACK);
jf.setLayout(new FlowLayout());
jf.setVisible(true);
jf.pack();
jf.setMinimumSize(jf.getSize());
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
};
SwingUtilities.invokeLater(r);
}
}
See Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? (Yes.)
Java GUIs might have to work on a number of platforms, on different screen resolutions & using different PLAFs. As such they are not conducive to exact placement of components or sizing of containers. To organize the components for a robust GUI, instead use layout managers, or combinations of them1, along with layout padding & borders for white space2.
jf.setContentPane(h);
i think u missed to set it as contentpane so it is just another panel
But when I am trying to setSize() with different sizes, red area does not contract or expend why is it so?
Because you are using FlowLayout() for your Jframe. Try to use different layout to do what you expect.Like:
Replace
jf.setLayout(new FlowLayout());
By
jf.setLayout(new BorderLayout());
Now change the size in setSize() you will get output as you expect.
For more help see Layout Managers
Option 1: Use setPreferredSize() instead of setSize(). It will run as expected. Panel will take size as mentioned (400 * 400) with red backbng color.
Option 2: If you will comment this line (jf.setLayout(new FlowLayout());) it will paint whole frame red as panel will occupy whole frame size.
Check why this is happening in the following post:
Java: Difference between the setPreferredSize() and setSize() methods in components.