void setUpGUI() {
JFrame frame = new JFrame();
frame.setContentPane(new Board());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setVisible(true);
}
class Board extends JPanel {
#Override
public void paintComponent(Graphics g) {
setLayout(new GridLayout(10, 9));
JButton b = new JButton("hello");
add(b);
g.setColor(Color.orange);
g.fillRect(20, 50, 100, 100);
}
}
For some reason the code only shows the rectangle, not the JButton. What am I doing wrong? Thanks!
The paintComponent() method is for painting only. You never create and add components to a panel in a painting method. Get rid of that code.
Also add a super.paintComponent() at the start of the method.
To add components to a panel you do something like:
Board board = new Board();
board.setLayout(...)
board.add(...);
or in the constructor of the board class you can set the layout and add components.
Related
I'm trying to create an interface with Swing.
This is my code:
public class JavaApplication30
{
public static void main(String[] args) throws IOException
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.X_AXIS));
frame.setPreferredSize(new Dimension(1280, 720));
frame.setResizable(false);
frame.setContentPane(new JPanel()
{
BufferedImage image = ImageIO.read(new File("C:\\Users\\user\\Documents\\NetBeansProjects\\JavaApplication29\\src\\eila.jpg"));
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image, 0, 0, 1280, 720, this);
}
});
JPanel a = new JPanel();
a.setAlignmentX(Component.LEFT_ALIGNMENT);
a.setPreferredSize(new Dimension(150, 500));
a.setMaximumSize(new Dimension(150, 500));
a.setOpaque(false);
a.add(Box.createRigidArea(new Dimension(5,50)));
JButton amico = new JButton("Amico");
a.add(amico);
a.add(Box.createRigidArea(new Dimension(5,20)));
amico.setPreferredSize(new Dimension(150, 50));
JButton bello = new JButton("Bello");
a.add(bello);
a.add(Box.createRigidArea(new Dimension(5,20)));
bello.setPreferredSize(new Dimension(150, 50));
JButton compagno = new JButton("Compagno");
a.add(compagno);
compagno.setPreferredSize(new Dimension(150, 50));
frame.getContentPane().add(a);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class ImagePanel extends JComponent {
private Image image;
public ImagePanel(Image image) {
this.image = image;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
I set the button alignment to the left, but my buttons are still centered.
This didn't happen without paintComponent for the background.
Why is this? How can I align the buttons on the left?
I set Alignment to left, but my buttons are centered
The setAlignmentX(...) is only a hint for how the "panel" should be aligned in its parent panel. When you add the buttons to the panel, what matters is the layout manager of the panel.
By default a JPanel uses a FlowLayout. Also by default when you create a FlowLayout, the components added to the panel are centered aligned in the space of the panel.
Change the layout manager to be a FlowLayout with the components left aligned. Read the FlowLayout API for the proper constructor to use.
Also, you can provide a default gap between the buttons, so there is no need for the Box.createRigidArea(...). The component is really meant to be used when you use a BoxLayout.
I am a beginner to JAVA and I'm breaking my head on the following problem:
Why does this code not draw
import ...
public class tekening extends JFrame{
private JPanel p;
private Graphics g;
tekening(){
setLayout(new FlowLayout());
p = new JPanel();
p.setPreferredSize(new Dimension(350, 350));
p.setBackground(Color.WHITE);
add(p);
setLocationByPlatform(true);
setSize(400, 400);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
g = p.getGraphics();
g.setColor(Color.BLACK);
g.drawRect(30, 30, 80, 40);
g.drawLine(10, 10, 40, 50);
}
}
And why does this code draw
import ...
public class tekenclasse extends JFrame implements ActionListener{
private JPanel p;
private Graphics g;
private JButton button1;
tekenclasse(){
setLayout(new FlowLayout());
button1 = new JButton("Knop 1");
button1.addActionListener(this);
add(button1);
p = new JPanel();
p.setPreferredSize(new Dimension(350, 350));
p.setBackground(Color.WHITE);
add(p);
setLocationByPlatform(true);
setSize(400, 400);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e){
g = p.getGraphics();
g.setColor(Color.BLACK);
g.drawRect(30, 30, 80, 40);
g.drawLine(10, 10, 40, 50);
}
}
For me this is completely strange. Why can't I use the Graphics inside the constructor. And why can I use it after an event. This is stupid I want to draw on immediately and I don't want to press a button.
Never use getGraphics() to paint.
Don't try and paint on top level containers like JFrame
Instead (as shown in Performing Custom Painting - MUST READ), use a JPanel (or JComponent) and override its protected void paintComponent(Graphics g) method. Use that graphics context to do your painting. All your painting should be done within that graphics context provides, whether directly writing code in the paintComponent method, or calling a method in which you pass the Graphics object to as an argument.
Override public Dimension getPreferredSize() in the JPanel/JComponent to give you painting surface a preferred size. Ad the pabel to the frame, then pack() your frame.
public class DrawPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.draw... // do all your drawing here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
Important: You MUST read the link about custom painting before posting another question about painting, or you will get a spanking :-)
So I set the setSize(500,500).. add some panels, the sum of panels Y is 500 like the JFrame but executing it shows an count Y of 525 am I missing something?
JPanel panel = new JPanel();
panel.setLayout(null);
getContentPane().add(panel);
//--------------------
JPanel top_panel = new JPanel();
top_panel.setLayout(null);
top_panel.setBackground(Color.blue);
top_panel.setBounds(0, 0, 500, 40);
panel.add(top_panel);
//------------------------------
JPanel middle_panel = new JPanel();
middle_panel.setLayout(null);
middle_panel.setBackground(Color.yellow);
middle_panel.setBounds(0, 40, 500, 385);
panel.add(middle_panel);
//-----------------------------
JPanel bottom_panel = new JPanel();
bottom_panel.setLayout(null);
bottom_panel.setBackground(Color.black);
bottom_panel.setBounds(0, 425, 500, 75);
panel.add(bottom_panel);
setSize(500,500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
setLocationRelativeTo(null);
40+385+75 = 500 but to show all the panels i must
setSize(500,525);
then it fits
here's an image:
The frame size is the light blue rectangle outside bounds including the title bar. Your panels are appearing in the inner bounds which is frame size less than the frame border and frame title bar. Do you see how your marked space at the bottom is strangely the same height as the title bar?
After adding your panels/component to the frame and just before calling frame.setVisible(true), call frame.pack().
It would be also preferable if you embrace a layout manager (such as FlowLayout) and when necessary call setPreferredSize and let the layout manager do the layout. Normally one would call setPreferredSize over setBound, setSize, setMininumSize, setMaximumSize.
import javax.swing.*;
import java.awt.*;
public class FrameSize {
private JFrame frame;
FrameSize create() {
frame = createFrame();
frame.getContentPane().add(createContent());
return this;
}
private JFrame createFrame() {
JFrame frame = new JFrame(getClass().getName());
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
return frame;
}
void show() {
// frame.setSize(500, 500);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
private Component createContent() {
JPanel panel = new JPanel(null);
JPanel topPanel = new JPanel(null);
topPanel.setBackground(Color.blue);
topPanel.setBounds(0, 0, 500, 40);
panel.add(topPanel);
JPanel middlePanel = new JPanel(null);
middlePanel.setBackground(Color.yellow);
middlePanel.setBounds(0, 40, 500, 385);
panel.add(middlePanel);
JPanel bottomPanel = new JPanel(null);
bottomPanel.setBackground(Color.black);
bottomPanel.setBounds(0, 425, 500, 75);
panel.add(bottomPanel);
panel.setPreferredSize(new Dimension(500, topPanel.getBounds().height + middlePanel.getBounds().height + bottomPanel.getBounds().height));
return panel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new FrameSize().create().show();
}
});
}
}
You shouldn't be setting size or calling setSize(...) or setBounds(...) as that's setting you up for similar problems in the future, or worse problems when you try to show your GUI on a different platform. Instead let the preferredSizes of your components and the layout managers do this work for you. If you absolutely must set the size of a component, then override getPreferredSize() and return a Dimension that is calculated to work for you. And yes, as per javajon, you should call pack() on the JFrame before displaying it.
For more discussions on the null layout, please read what one of the best Swing experts on this site, MadProgrammer, has to say in his answer here.
I have created an Object that extends JPanel and draws beginning at (0,0) a short animation). It works great on its own but I would like to add a button above it to handle small actions for the animation.
So in my main class I did the following:
JFrame f = new JFrame("Test");
JButton testButton = new Button("BUTTON");
MyAnimationDrawer drawing1 = new MyAnimationDrawer();
What i want to do:
How would I add the button and my Object to the JFrame so that the top left corner acts as (0,0)? Exactly as shown in my image link.
By using BorderLayout.
Add drawing panel on CENTER of JFrame. Something like:
frame.add(drawingPanel, BorderLayout.CENTER);
Add button on upper panel and then add upper panel on NORTH of JFrame:
upperPanel.add(button);
frame.add(upperPanel, BorderLayout.NORTH);
As brano88 has stated, the simplest way to achieve this is by using BorderLayout. Below is a short example of what you desire using this layout. As BorderLayout is the default layout manager for a JFrame, you do not need to explicitly set it, just use its fields out of the box.
public class MyPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
public static void main(String[] args){
JFrame frame = new JFrame("My frame");
frame.setSize(800,600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
//Button Panel
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton("Click me!"));
//Drawing panel
MyPanel panel = new MyPanel();
frame.add(panel, BorderLayout.CENTER);
frame.add(buttonPanel, BorderLayout.NORTH);
frame.setVisible(true);
}
}
I am trying to add a JPanel (well, several) to a JLayeredPane. However, when I do so, the paint component method of the JPanel seems to have no effect. An example is included below:
import javax.swing.*;
import java.awt.*;
public class Example {
public static void main(String[] args) {
// This Works as expected
JFrame usingPanel = new JFrame();
JPanel p = new JPanel();
p.add(new BluePanel());
usingPanel.setContentPane(p);
usingPanel.pack();
usingPanel.setVisible(true);
// This makes the frame but does not paint the BluePanel
JFrame usingLayer = new JFrame();
JLayeredPane l = new JLayeredPane();
l.setPreferredSize(new Dimension(200,200));
l.add(new BluePanel(), JLayeredPane.DEFAULT_LAYER);
JPanel p2 = new JPanel();
p2.add(l);
usingLayer.setContentPane(p2);
usingLayer.pack();
usingLayer.setVisible(true);
}
static class BluePanel extends JPanel{
public BluePanel(){
setPreferredSize(new Dimension(200,200));
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(0, 0, 200, 200);
}
}
}
Why is this? and what are the possible solutions?
JLayeredPane does not have a LayoutManager, so you need to set the location and size of your panels yourself.
See the tutorial
you hardcoded the size on the screen and have to change from
g.fillRect(0, 0, 200, 200);
to
g.fillRect(0, 0, getWidth(), getHeight());
(a minor change) add the method
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
and then remove of code line setPreferredSize(new Dimension(200,200));